HAL RCC clock recovery system (CRS) function control

The goal of this page is to show how to migrate the initialization sequence using STM32CubeMX2:

  • Open STM32CubeMX2 CRS configuration panel.

  • Configure the HAL SW layer.

  • Configure the main CRS features.

  • Configure the NVIC if the application requires the CRS to be used in IT mode.

  • Generate the code.

HAL CRS configuration panel

Create a new project with the STM32CubeMX2, then start the initialization and the main configuration.

Project configuration panel

HAL CRS main features configuration

Configure the CRS main features.

CRS main feature configuration

NVIC configuration

Configure the NVIC in case of an interrupt.

CRS NVIC configuration

Generated CRS initialization and de-initialization sequences

The CRS initialization and de-initialization sequences are generated in the mx_crs_init function in the mx_crs.c file under $YOUR_PROJECT_NAME$/$YOUR_PROJECT_NAME$_SW/generated/STM32Cube_CodeGen.

Note

In HAL1, the Clock Recovery System (CRS) functionality is integrated within the RCC driver. As a result, the generated CRS-related initialization code is not placed in the MSP file, but is instead included together with the RCC configuration code in the main.c file.

STM32CubeMX2 Generated with user values

Topic

HAL1 code snippet

HAL2 code snippet

Initialization and configuration sequence

/*  */

RCC_CRSInitTypeDef RCC_CRSInitStruct = {0};





/** Enable the CRS APB clock */
__HAL_RCC_CRS_CLK_ENABLE();
/** Configures CRS */
RCC_CRSInitStruct.Prescaler = RCC_CRS_SYNC_DIV16;
RCC_CRSInitStruct.Source = RCC_CRS_SYNC_SOURCE_GPIO;
RCC_CRSInitStruct.Polarity = RCC_CRS_SYNC_POLARITY_RISING;
RCC_CRSInitStruct.ReloadValue = 0xBB7F;
RCC_CRSInitStruct.ErrorLimitValue = 0x22;
RCC_CRSInitStruct.HSI48CalibrationValue = 0x30;
/* The Auto Trimming is internally enabled in HAL_RCCEx_CRSConfig() */

HAL_RCCEx_CRSConfig(&RCC_CRSInitStruct);

static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOB_CLK_ENABLE();







   /*Configure GPIO pin : PB3 */
   GPIO_InitStruct.Pin = GPIO_PIN_3;
   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

   GPIO_InitStruct.Pull = GPIO_NOPULL;
   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
   GPIO_InitStruct.Alternate = GPIO_AF10_CRS;
   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);


 }
hal_crs_handle_t *mx_crs_init(void)
{
  hal_crs_config_t crs_config;

  if (HAL_CRS_Init(&hCRS, HAL_CRS1) != HAL_OK)
  {
    return NULL;
  }

  HAL_RCC_CRS_EnableClock();

  crs_config.divider                = HAL_CRS_SYNC_DIV16;
  crs_config.source                 = HAL_CRS_SYNC_SOURCE_GPIO;
  crs_config.polarity               = HAL_CRS_SYNC_POLARITY_RISING;;
  crs_config.reload                 = 0xBB7F;
  crs_config.frequency_error_limit  = 0x22;
  crs_config.trimming               = 0x30;
  crs_config.auto_trimming          = HAL_CRS_AUTO_TRIMMING_ENABLE;

  HAL_CRS_SetConfig(&hCRS, &crs_config);



  hal_gpio_config_t  gpio_config;


  HAL_RCC_GPIOB_EnableClock();

  /**
    CRS GPIO Configuration

    [GPIO Pin] ------> [Signal Name]

       PB3     ------>   CRS_SYNC
    **/

  gpio_config.mode        = HAL_GPIO_MODE_ALTERNATE;
  gpio_config.output_type = HAL_GPIO_OUTPUT_PUSHPULL;
  gpio_config.pull        = HAL_GPIO_PULL_NO;
  gpio_config.speed       = HAL_GPIO_SPEED_FREQ_LOW;
  gpio_config.alternate   = HAL_GPIO_AF_0;
  HAL_GPIO_Init(HAL_GPIOB, HAL_GPIO_PIN_3, &gpio_config);

  return &hCRS;
 }

Deinitialization sequence

/*  Not available */
void mx_crs_deinit(void)
{
  (void)HAL_CRS_DeInit(&hCRS);

  /* De-initialize all GPIO pins associated with CRS */
  HAL_GPIO_DeInit(HAL_GPIOB, HAL_GPIO_PIN_3);

  HAL_RCC_CRS_Reset();
  HAL_RCC_CRS_DisableClock();
}

Note

In the previous example, the CRS synchronization source is set to GPIO. Therefore, the Init and DeInit sequences should take into consideration the initialization and deinitialization of the GPIO.

Note

The synchronization sources may vary from one series to another.

HAL RCC CRS Control Functions

Start synchronization

HAL1

HAL2

In HAL1, the HAL_RCCEx_CRSConfig function is used to:

  • Configure the Clock Recovery System (CRS).

  • Start the CRS driver.

  • Enable the auto trimming.

In HAL2, this functionality is split into the following functions:

  • HAL_CRS_SetConfig: Set the configuration.

  • HAL_CRS_EnableAutoTrimming: Enable the auto trimming.

  • HAL_CRS_StartSync: Enable the frequency error counter.

void HAL_RCCEx_CRSConfig(const RCC_CRSInitTypeDef *const pInit);
hal_status_t HAL_CRS_SetConfig(hal_crs_handle_t *hcrs, const hal_crs_config_t *p_config);
hal_status_t HAL_CRS_EnableAutoTrimming(hal_crs_handle_t *hcrs);
/* Start the driver with Frequency Error Counter enabled in Polling mode     */
hal_status_t HAL_CRS_StartSync(hal_crs_handle_t *hcrs);

Related use case: Enable synchronization in polling mode

HAL RCC CRS Software Synchronization Generate

Function Description

HAL1

HAL2

In HAL1, the HAL_RCCEx_CRSSoftwareSynchronizationGenerate function is used to generate a software synchronization event for the Clock Recovery System (CRS).

In HAL2, this functionality is provided by the HAL_CRS_GenerateSoftwareSync function, which uses a handle to the CRS instance to perform the synchronization.

void HAL_RCCEx_CRSSoftwareSynchronizationGenerate(void);
hal_status_t HAL_CRS_GenerateSoftwareSync(hal_crs_handle_t *hcrs);

Related use case: Software synchronization

HAL RCC CRS Get Synchronization Info

HAL1

HAL2

In HAL1, the HAL_RCCEx_CRSGetSynchronizationInfo function is used to retrieve synchronization information for the Clock Recovery System (CRS).

In HAL2, this functionality is expanded into multiple functions to provide more detailed configuration and status information:

  • HAL_CRS_GetFrequencyErrorInfo: Retrieves frequency error information (frequency error capture and direction) for the CRS.

  • HAL_CRS_GetConfig: Retrieves the configuration of a specified CRS instance. This function gets multiple parameter values. If user wants to get only the reload value, use LL_CRS_GetReloadCounter instead.

  • HAL_CRS_GetTrimming: Retrieves the current trimming value of the CRS.

void HAL_RCCEx_CRSGetSynchronizationInfo(RCC_CRSSynchroInfoTypeDef *pSynchroInfo);
void HAL_CRS_GetFrequencyErrorInfo(const hal_crs_handle_t *hcrs,
                                    hal_crs_frequency_error_info_t *p_frequency_error_info);

/* If user needs to retrieve the configuration and init value that he
   already applied, call HAL_CRS_GetConfig() and HAL_CRS_GetTrimming() */
void HAL_CRS_GetConfig(const hal_crs_handle_t *hcrs, hal_crs_config_t *p_config);
uint32_t HAL_CRS_GetTrimming(const hal_crs_handle_t *hcrs);

HAL RCC CRS Wait for synchronization

HAL1

HAL2

In HAL1, the HAL_RCCEx_CRSWaitSynchronization function is used to wait for the synchronization of the Clock Recovery System (CRS) to complete within a specified timeout.

In HAL2, this functionality is provided by the HAL_CRS_PollForSync function, which uses a handle to the CRS instance and specifies the timeout in milliseconds.

uint32_t HAL_RCCEx_CRSWaitSynchronization(uint32_t Timeout);
hal_status_t HAL_CRS_PollForSync(hal_crs_handle_t *hcrs, uint32_t timeout_ms);

HAL RCC CRS IRQHandler and Callback Functions

Function Description

HAL1

HAL2

void HAL_RCCEx_CRS_IRQHandler(void);
void HAL_CRS_IRQHandler(hal_crs_handle_t *hcrs);
void HAL_RCCEx_CRS_SyncOkCallback(void);
void HAL_CRS_SyncOkCallback(hal_crs_handle_t *hcrs);
void HAL_RCCEx_CRS_SyncWarnCallback(void);
void HAL_CRS_SyncWarnCallback(hal_crs_handle_t *hcrs);
void HAL_RCCEx_CRS_ExpectedSyncCallback(void);
void HAL_CRS_ExpectedSyncCallback(hal_crs_handle_t *hcrs);
void HAL_RCCEx_CRS_ErrorCallback(uint32_t Error);
void HAL_CRS_ErrorCallback(hal_crs_handle_t *hcrs);

HAL RCC CRS Callback Register Functions

HAL1

HAL2

In HAL1, callback handling is done by overriding the default weak callback functions provided by the HAL driver in the user application code.

HAL2 provides weak callbacks as per HAL1 that are the following:

__WEAK void HAL_CRS_SyncOkCallback(hal_crs_handle_t *hcrs)
__WEAK void HAL_CRS_SyncWarnCallback(hal_crs_handle_t *hcrs)
__WEAK void HAL_CRS_ExpectedSyncCallback(hal_crs_handle_t *hcrs)
__WEAK void HAL_CRS_ErrorCallback(hal_crs_handle_t *hcrs)

HAL2 provides also callback registration possibility with the following functions:

hal_status_t HAL_CRS_RegisterSyncOkCallback(hal_crs_handle_t *hcrs, hal_crs_cb_t p_callback);
hal_status_t HAL_CRS_RegisterSyncWarnCallback(hal_crs_handle_t *hcrs, hal_crs_cb_t p_callback);
hal_status_t HAL_CRS_RegisterExpectedSyncCallback(hal_crs_handle_t *hcrs, hal_crs_cb_t p_callback);
hal_status_t HAL_CRS_RegisterErrorCallback(hal_crs_handle_t *hcrs, hal_crs_cb_t p_callback);